import os, string
import time
from stat import ST_MODE, ST_MTIME
import vcs
from vcs import TEST, TRUE, FALSE, NL, SYSTEM, WINDOWS, UNIX, NULLDEV
from cclog import CClog
from YesNoDialog import YesNoDialog
from etgui import ShowDialog

_TMPCMD = 'clearcase.tmp'
_LABELS = {}

def askYesNo(title, text):
	dlg = YesNoDialog(title, text)
	ShowDialog(dlg)
	return dlg.Answer()
 
# ---- log handling ----------------------------------

_last_rep_file		= ''
_last_log		= None

def log_with_history(use_cache=FALSE):
	global _last_rep_file, _last_log
	if use_cache and _last_rep_file == vcs.repositoryFile:
		_last_log.reuse()
		return _last_log
	else:
		if string.find(vcs.repositoryFile, ' ') > 0:	# multiple files
			return CClog(vcs.repositoryFile, vcs.workingFile)
		_last_log = CClog(vcs.repositoryFile, vcs.workingFile)
		_last_log.close()
		_last_rep_file = vcs.repositoryFile
		if not _last_log:
			_last_rep_file = ''
		return _last_log
 
# ---- ClearCase utils -------------------------------

def mklbtype(label):
	if not _LABELS.has_key(label):
		os.chdir(vcs.repositoryDir)
		rc = vcs.system('cleartool mklbtype -nc %s\n' % label)
		if rc==0:
			global _LABELS
			_LABELS[label] = None

# ----------------------------------------------------
# ---- VCS commands ----------------------------------
# ----------------------------------------------------

def CheckOut():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	if vcs.workingDir == vcs.tmpDir:
		if vcs.revision:
			if os.path.basename(vcs.revision) == '0':
				vcs.rm_f(vcs.tmpFile)
				vcs.touch(vcs.tmpFile)
				return TRUE
		rc = vcs.cp('%s@@%s' % (path, vcs.normpath(vcs.revision)), vcs.tmpFile)
	elif vcs.lockType == 'E':
		rc = vcs.system( 'cleartool co -nc -reserved %s' % path )
	else: 
		rc = vcs.system( 'cleartool co -nc -unreserved %s' % path )
	return vcs.test(rc)


def CheckOutProject():
	return TRUE


def CreateRepositoryFile():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	comment = vcs.escape_quotes(vcs.comment)
	desc = vcs.escape_quotes(vcs.description)
	parent = vcs.normpath(vcs.repositoryDir)
	if not vcs.getoutput('cleartool lsc -me -d %s' % parent):
		doco = askYesNo("Checkout directory",
						"Directory element " + 
						"@B" + parent + "@B " + 
						"is not checked out. " +
						"Check it out now?")
		if doco:
			vcs.system('cleartool co -nc -reserved %s\n' % parent)
	rc = vcs.system('cleartool mkelem -c "%s" %s' % (desc, path))
	if not rc:
		rc = vcs.system('cleartool ci -c "%s" %s' % (comment, path))
	if rc:
		return FALSE
	if vcs.symbolName:
		mklbtype(vcs.symbolName)
		args = (vcs.symbolName, path)
		vcs.system('cleartool mklabel -nc -version "/main/1" %s %s\n' % args)
	if vcs.lockType == 'E':
		rc = vcs.system('co -nc -reserved %s\n' % path)
	return vcs.test(rc)


def CheckIn():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	comment = vcs.escape_quotes(vcs.comment)
	ident = ''
	if vcs.forceFlag:
		ident = '-identical'
	rc = vcs.system('cleartool ci %s -c "%s" %s' % (ident, comment, path))
	if rc: return FALSE
	if vcs.symbolName:
		mklbtype(vcs.symbolName)
		args = (vcs.symbolName, path)
		vcs.system('cleartool mklabel -nc %s %s\n' % args)
	if vcs.lockType == 'E':
		rc = vcs.system('co -nc -reserved %s\n' % path)
	return vcs.test(rc)


def Lock():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	rc = vcs.system('cleartool reserve -nc %s' % path)
	return vcs.test(rc)


def SetWorkFileReadOnly():
	return TRUE


def UpdateProject():
	return TRUE


def UpdateFile():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	if vcs.revision:
		V = '-fversion %s' % vcs.normpath(vcs.revision)
	else:
		V = '-flatest'
	out = vcs.getoutput('cleartool findmerge %s -nc -print %s -whynot' % (path, V))
	vcs.output(out)
	return TRUE


def Unlock():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	rc = vcs.system('cleartool unreserve -nc %s' % path)
	return vcs.test(rc)


def BreakLock():
	return TRUE


def DeleteVersion():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	if vcs.revision:
		path = '%s@@%s' % (path, vcs.normpath(vcs.revision))
	rc = vcs.system('cleartool rmver -force -xlabel %s' % path)
	return vcs.test(rc)


def SetDescription():
	#vcs.output('ClearCase does not support Description')
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	desc = vcs.escape_quotes(vcs.description)
	args = (desc, path)
	rc = vcs.system('cleartool chevent -c "%s" -replace %s@@' % args)
	return vcs.test(rc)


def SetSymbol():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	if vcs.forceFlag:
		F = '-replace'
	else:
		F = ''
	if vcs.revision:
		V = '-version %s' % vcs.normpath(string.rstrip(vcs.revision))
	else:
		V = ''
	mklbtype(vcs.symbolName)
	args = (F, V, vcs.symbolName, path)
	rc = vcs.system('cleartool mklabel %s %s "%s" %s' % args)
	return vcs.test(rc)


def DeleteSymbol():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	if vcs.revision:
		V = '-version ' + vcs.normpath(vcs.revision)
	else:
		V = ''
	rc = vcs.system('cleartool rmlabel %s "%s" %s' % (V, vcs.symbolName, path))
	return vcs.test(rc)


def ChangeComment():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	comment = vcs.escape_quotes(vcs.comment)
	args = (comment, path, vcs.normpath(vcs.revision))
	rc = vcs.system('cleartool chevent -c "%s" -replace %s@@%s' % args)
	return vcs.test(rc)


def Description():
	log = log_with_history(TRUE)
	if not log:
		return FALSE
	vcs.output(log.description)
	return TRUE


def History():
	log = log_with_history(TRUE)
	if not log:
		return FALSE
	vcs.output(string.join(log.history, NL))
#    out = vcs.getoutput('cleartool annotate -nco -ndata -out - -long %s' % path)
#or
#    out = vcs.getoutput('cleartool lsh -fmt "%%e %%Vn %%u %%Vd %%Nl\\n%%c" %s' % path)
#    vcs.output(out)
	return TRUE
 

def Head():
	return TRUE


def SymbolList():
	log = log_with_history(FALSE)
	if not log:
		return FALSE
	out_list = []
	while log:
		out_list.append('\014%s' % log.work_file())
		symbols = log.symbolstr()
		if symbols:
			out_list.append(symbols)
		for rev in log.revision_list():
			out_list.append(string.join((rev.ccrev, rev.rev, rev.date, rev.author, rev.lines)))
		log.next()
	vcs.output(string.join(out_list, NL))
	return TRUE


def RevisionOfSymbol():
	log = log_with_history(TRUE)
	if not log:
		return FALSE
	for rev in log.revisions:
		if vcs.symbolName in rev.labels:
			vcs.output(rev.ccver)
			return TRUE
	return FALSE


def HistoryOfRevision():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	args = (vcs.normpath(vcs.revision), path)
	out = vcs.getoutput('cleartool describe -version %s %s' % args)
	vcs.output(out)
	return TRUE


def Comment():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	args = (vcs.normpath(vcs.revision), path)
	out = vcs.getoutput('cleartool describe -fmt "%%c" -version %s %s' % args)
	vcs.output(out)
	return TRUE


def Lockers():
	os.chdir(vcs.repositoryDir)
	wfiles = string.split(vcs.workingFile)
	wfiles = map(vcs.normpath, wfiles)
	out = vcs.getoutput('cleartool lsc ' + string.join(wfiles))
	processed = {}
	out_list = []
	for line in string.split(out, NL):
		fields = string.split(line, "checkout version")
		if len(fields) != 2:
			continue
		left, right = fields
		b = string.find(left, ' ')
		user = string.strip(left[b:])
		rfields = string.split(right)
		(file, ver, flag) = rfields[0], rfields[2], rfields[3]
		file = file[1:-1]
		try:
			lock = processed[file]
		except KeyError:
			lock = ''
		processed[file] = lock + ' %s:%s:(%s)' % (user, ver, flag[1:2])
	for file in string.split(vcs.workingFile):
		try:
			out_list.append(file+processed[file])
		except KeyError:
			out_list.append(file)
	vcs.output(string.join(out_list,NL))
	return TRUE


def IsLockedBy():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	rc = vcs.system('cleartool lsc -user %s %s' % (vcs.user, path))
	return vcs.test(rc) 


def IsLocked():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	rc = vcs.system('cleartool lsc %s' % path)
	return vcs.test(rc) 


def RepositoryDir():
	vcs.output(vcs.joinpath(vcs.RCCSPath, vcs.catDir))
	return TRUE

def RepositoryFile():
	vcs.output(vcs.joinpath(vcs.repositoryDir, vcs.workingFile))
	return TRUE

def TempDir():
	vcs.output(vcs.joinpath(vcs.OSTempDir, '.sniffdir2', 
							'ClearCase_%s%s' % (vcs.UserName(), vcs.pid)))
	return TRUE

def TempFile():
	vcs.output(vcs.joinpath(vcs.tmpDir, vcs.workingFile))
	return TRUE

def BranchDef():
	vcs.output('')
	return TRUE

def RepositoryCheckDef():
	vcs.output('C')
	return TRUE


def IsDifferent():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	if vcs.is_writable(path):
		rc = vcs.system('cleartool diff -diff_format -pred %s > %s' % (path, NULLDEV))
		return vcs.test(rc)
	return TRUE


def DiffText_W_V():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	if vcs.revision2:
		V = vcs.normpath(vcs.revision2)
	else:
		# get latest version on version tree (HEAD)
		out = vcs.getoutput('cleartool lsvtree -nco %s' % path)
		out = string.rstrip(out)	    # strip trailing newline chars
		last = out[string.rfind(out, NL):]  # get last line
		file = string.split(last)[0]	    # format: file [labels]
		V = string.split(file,'@@')[1]	    # extract version extension
		V = vcs.normpath(V)
	out = vcs.getoutput('cleartool diff -diff_format %s %s@@%s' % (path, path, V))
	vcs.output(out)
	return out == ''


def DiffText_V_V():
	path = vcs.joinpath(vcs.repositoryDir, vcs.workingFile)
	args = (path, vcs.normpath(vcs.revision), path, vcs.normpath(vcs.revision2))
	out = vcs.getoutput('cleartool diff -diff_format %s@@%s %s@@%s' % args)
	vcs.output(out)
	return out == ''


def CheckRepositoryDir():
	return TRUE


def CheckRepositoryFile():
	path = os.path.join(vcs.repositoryDir, vcs.workingFile)
	st = vcs.get_stat(path+'@@')
	return vcs.test_exists(st)


def DateOfRepositoryFile():
	path = os.path.join(vcs.repositoryDir, vcs.workingFile)
	out = ''
#	use the following line to test for new labels, etc.
#	(It will slow down filtering modified files)
#	out = vcs.getoutput('cleartool lsh -minor -since today -fmt "%%Vd\n" %s' % path)
	if out:
		day_date_time = out[:string.find(out, '\n')]
		[day, date, timestr] = string.split(day_date_time)
		[month, day, year] = string.split(date, '/')
		vcs.output('%s/%s/%s %s' % (year, month, day, timestr))
	else:
		mtime = vcs.get_stat(path)[ST_MTIME]
		if not mtime:
			mtime = time.time()
		vcs.output(time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(mtime)))
	return TRUE
 

def CreateRepositoryDir():
	return TRUE


def TestTool():
	return vcs.is_reachable('cleartool')
 

def Constructor():
	global TMPCMD, _TMPCMD
	TMPCMD = vcs.joinpath(vcs.tmpDir, _TMPCMD)
	if not os.path.isdir(vcs.tmpDir):
		rc = vcs.mkdir_p(vcs.tmpDir)
		return vcs.test(rc)
 
	return TRUE


def Destructor():
	if os.path.isdir(vcs.tmpDir):
		rc = vcs.rm_fr(vcs.tmpDir)
		return vcs.test(rc)
	return TRUE
 
